<?php
/**---------------------------------------------------------------------------
 * Purpose：	Database Connection
 * 
 * CreateDate : 2012/12/25
 * Description：
 * 	データベースの接続、選択などの一連の処理を行なう
 *  Connect to database and run query statement.
 * @package    C-UNIT Class
 * @author     C-UNIT SQUARE CO.,LTD. <info@c-unit.co.jp>
 * @copyright  Copyright(c) 2012　C-UNIT SQUARE CO.,LTD. All Rights Reserved.
 * @license    C-UNIT SQUARE CO.,LTD.
 ---------------------------------------------------------------------------*/
class CUnit_DataBaseCls
{
    protected $_objDB;			// データベースオブジェクト
    protected $_strDbName;		// データベース名

    /**----------------------------------------------------------------------
     * クラスプロパティ
     ----------------------------------------------------------------------*/
    public function getDb()
    {
        return $this->_objDB;
    }

    /**----------------------------------------------------------------------
     * コンストラクタ(DBへの接続を行う)
     *
     * @param   none
     * @return  none
     *
     ----------------------------------------------------------------------*/
    public function __construct()
    {
        // iniファイルよりDataBase項目の値を取得
		$objConfig  = CUnit_Config::getConfig();

        // DB接続のパラメータを定義する
        $arrParams = array('host'   	=>$objConfig->production->resources->db->params->host,
                           'username'  =>$objConfig->production->resources->db->params->username,
                           'password'  =>$objConfig->production->resources->db->params->password,
                           'dbname'    =>$objConfig->production->resources->db->params->dbname
						);

        // DB名を退避（setPrimaryKeyで利用）
        $this->_strDbName = $objConfig->production->resources->db->dbname;

        // DBに接続
        $this->_objDB = Zend_Db::factory($objConfig->production->resources->db->adapter, $arrParams);

        // DBの文字コードを設定
		
        if (isset($objConfig->production->resources->db->setnames) && $objConfig->production->resources->db->setnames != ''){
            $this->_objDB->query('set names ' . $objConfig->production->resources->db->setnames);
        }
    }

    /**----------------------------------------------------------------------
     * プライマリキーのカラム名の取得（MySQL用）
     *
     * @param   string  $strTableName
     * @return  none
     *
     ----------------------------------------------------------------------*/
    public function setPrimaryKey($strTableName)
    {
        // 配列の取得方法の指定。結果を連想配列の配列として返します。 配列のキーは、カラム名を文字列で表したものとなります
        $this->_objDB->setFetchMode(Zend_Db::FETCH_ASSOC);

        // SQL文を構築（主キー項目を取得）
        $strItem   = "COLUMN_NAME";
        $strTable  = "INFORMATION_SCHEMA.KEY_COLUMN_USAGE";
        $strWhere  = "TABLE_NAME = ? AND "
                   . "CONSTRAINT_NAME = 'PRIMARY' AND "
                   . "CONSTRAINT_SCHEMA = ? "
                   ;
        $strWhereEscape = array($strTableName, $this->_strDbName);

        // SQL文の実行
        $arrQuery = $this->selectDb($strItem, $strTable, $strWhere, $strWhereEscape);
        // プライマリーキーを返す
        return $arrQuery[0]['COLUMN_NAME'];
    }

    /**----------------------------------------------------------------------
     * Get table columns
     *
     * @param   string  $strTableName
     * @return  mixed
     *
     ----------------------------------------------------------------------*/
    public function getColumns($strTableName)
    {
        // 配列の取得方法の指定。結果を連想配列の配列として返します。 配列のキーは、カラム名を文字列で表したものとなります
        $this->_objDB->setFetchMode(Zend_Db::FETCH_ASSOC);

        // SQL文を構築（主キー項目を取得）
        $strItem   = "COLUMN_NAME";
        $strTable  = "INFORMATION_SCHEMA.COLUMNS";
        $strWhere  = "TABLE_NAME = ? AND "
                   . "TABLE_SCHEMA = ? "
                   ;
        $strWhereEscape = array($strTableName, $this->_strDbName);

        // SQL文の実行
        $objResults = $this->selectDb($strItem, $strTable, $strWhere, $strWhereEscape);
		return $objResults;
    }

    /**----------------------------------------------------------------------
     * 文字列のエスケープ処理
     *
     * @param   array   $arrParams
     * @return  array   エスケープ後の文字列
     *
     ----------------------------------------------------------------------*/
    public function exchangeMq($arrParams = array())
    {
        // 変数初期化
        $arrReturns = array();

        // magic_quotes_gprがONの場合はstripslashesを実行
        if (get_magic_quotes_gpc() == true){
            foreach ($arrParams as $key => $value){
                $arrReturns[$key] = stripslashes(trim($value));
            }
        }else{
            foreach ($arrParams as $key => $value){
                $arrReturns[$key] = trim($value);
            }
        }

        return $arrReturns;
    }

    /**----------------------------------------------------------------------
     * データの選択を行う
     *
     * @param   string  $strItem           テーブルより取得する項目
     * @param   string  $strTable          対象となるテーブル
     * @param   string  $strWhere          SQLの条件文
     * @param   array   $arrWhereEscape    Where文のエスケープ文字列
     * @param   string  $strOption         その他SQLオプション(order by等の命令文も記述が必要)
     * @return  array   SQL文実行後の二次元配列([行番号][項目名])
     *
     ----------------------------------------------------------------------*/
    public function selectDb($strItem = '*', $strTable = '', $strWhere = '', $arrWhereEscape = array(), $strOption = '')
    {
        // ユーザー入力値のエスケープ処理
        if (isset($arrWhereEscape[0]) == true && $arrWhereEscape[0] !== ''){
            $arrWhereEscape = $this->exchangeMq($arrWhereEscape);
        }

        // 配列の取得方法の指定。結果を連想配列の配列として返します。 配列のキーは、カラム名を文字列で表したものとなります
        $this->_objDB->setFetchMode(Zend_Db::FETCH_ASSOC);

        // SQL文を構築
        $strSql =  "SELECT " . $strItem . " FROM " . $strTable;

        if ($strWhere !== ''){
            $strSql .=  " WHERE " . $strWhere;
        }

        if ($strOption !== ''){
            $strSql .=  ' ' . $strOption;
        }

        if (isset($arrWhereEscape[0]) == true && $arrWhereEscape[0] !== ''){
            // SQL文の実行
            $arrQuery = $this->_objDB->fetchAll($strSql, $arrWhereEscape);
        }else{
            // SQL文の実行
            $arrQuery = $this->_objDB->fetchAll($strSql);
        }

        /*if (strtoupper(DEBUG_MODE) === 'ON'){
            // デバッグモードONの場合はSQL文を表示
            Zend_Debug::dump($strSql, 'SQL文：');
            Zend_Debug::dump($arrWhereEscape, 'WHERE文パラメータ：');
            //Zend_Debug::dump($arrQuery, 'SQL実行結果：');
        }*/
        return $arrQuery;
    }

    /**----------------------------------------------------------------------
     * データの存在チェックを行う
     *
     * @param   string  $strTable          対象となるテーブル
     * @param   string  $strstrKeyValue       プライマリキー値
     * @return  boolean True:データあり  False:データなし
     *
     ----------------------------------------------------------------------*/
    public function checkData($strTable = '', $strstrKeyValue = '')
    {
        // ユーザー入力値のエスケープ処理
        $strstrKeyValue = $this->exchangeMq(array($strstrKeyValue));
        // フラグの初期化
        $blnFlg = false;
        // 主キー項目の取得
        $strPrimaryKey = $this->setPrimaryKey($strTable);

        // 配列の取得方法の指定。結果を連想配列の配列として返します。 配列のキーは、カラム名を文字列で表したものとなります
        $this->_objDB->setFetchMode(Zend_Db::FETCH_ASSOC);

        $strSql = "SELECT " . $strPrimaryKey . " FROM " . $strTable . " WHERE " . $strPrimaryKey . " = ? " ;
        // SQL文の実行
        $arrQuery = $this->_objDB->fetch($strSql, $strstrKeyValue);

        if (count($arrQuery) != 0){
            $blnFlg = true;
        }

        return $blnFlg;
    }
	/**----------------------------------------------------------------------
     * check Duplicated
     *
     * @param   string  $strTable          対象となるテーブル
	 * @param   string  $strFiled        filed
     * @param   string  $strValue       プライマリキー値
     * @return  boolean True:データあり  False:データなし
     *
     ----------------------------------------------------------------------*/
	 public function checkDuplicatedData($strTable = '', $strFiled = '', $strValue = '')
    {
		 // フラグの初期化
        $blnFlg = false;
		$strSql = "SELECT " . $strFiled . " FROM " . $strTable . " WHERE " . $strFiled . " = ? ";
        // SQL文の実行
        $arrQuery = $this->_objDB->fetchAll($strSql, $strValue);
		
		if (count($arrQuery) != 0){
            $blnFlg = true;
        }

        return $blnFlg;
    }
    /**----------------------------------------------------------------------
     * データの登録を行う（新規登録、更新は自動判別）
     *
     * @param   string  $arrParams         	更新するパラメータ（連想配列）
     * @param   string  $strTable          	対象となるテーブル
     * @param   string  $strKeyValue       	プライマリキーの値
     * @param   string  $blnLogin       	ログイン情報のみ更新ならtrue
     * @return  none
     *
     ----------------------------------------------------------------------*/
    public function updInsDb($arrParams = array(), $strTable = '', $strKeyValue = '', $blnLogin = false)
    {
        // ユーザー入力値のエスケープ処理
        $arrParams = $this->exchangeMq($arrParams);

        // Get table columns
        $arrCols = $this->getColumns($strTable);

        $blnCreateDate = false;
        $blnUpdateDate = false;

        foreach ($arrCols as $objCol){
            if (strtolower($objCol['COLUMN_NAME']) == 'create_date'){
                $blnCreateDate = true;
            }
			
            if (strtolower($objCol['COLUMN_NAME']) == 'update_date'){
                $blnUpdateDate = true;
            }
        }

        // 日付の取得
        $strDate = date('Y-m-d H:i:s');

        if ($blnLogin == false) {
        //「ログイン情報のみ更新」の場合は'update_date'は更新しない
            if ($blnUpdateDate){
                $arrParams['update_date'] = $strDate;
            }
        }

        if ($strKeyValue === '' || $strKeyValue == null){
			// キー値が入力されていない場合は新規登録
            if ($blnCreateDate){
                $arrParams['create_date'] = $strDate;
            }

            $this->_objDB->insert($strTable,$arrParams);
            return $this->_objDB->lastInsertId();
        }else{
        // 更新
            // 主キー項目の取得
            $key = $this->exchangeMq(array($strKeyValue));
            $strPrimaryKey = $this->setPrimaryKey($strTable);
            $strWhere = array($strPrimaryKey . " = " . $strKeyValue);
            return $this->_objDB->update($strTable, $arrParams, $strWhere);
        }
    }

	/**----------------------------------------------------------------------
     *
     * @param   string  $strTable          対象となるテーブル
     * @param   string  $arrParams         更新するパラメータ（連想配列）
     * @param   string  $strWhere          SQLの条件文
     * @return  none
     *
     ----------------------------------------------------------------------*/
    public function update($strTable, $arrParams, $strWhere)
    {
        $this->_objDB->update($strTable, $arrParams, $strWhere);
    }

    /**----------------------------------------------------------------------
     *
     * @param   string  $arrParams         	更新するパラメータ（連想配列）
     * @param   string  $strTable          	対象となるテーブル
	 * @param   integer $intFlag          	
     * @param   boolen  $blnLogin       	ログイン情報のみ更新ならtrue
     * @return  integer		last insert id
     *
     ----------------------------------------------------------------------*/
    public function insertDb($arrParams = array(), $strTable = '', $intFlag = 1, $blnLogin = false)
    {
        // ユーザー入力値のエスケープ処理
        $arrParams = $this->exchangeMq($arrParams);

        if($intFlag == 1){
            // Get table columns
            $arrCols = $this->getColumns($strTable);

            $blnCreateDate = false;
            $blnUpdateDate = false;
            foreach ($arrCols as $col){
                if (strtolower($col['COLUMN_NAME']) == 'create_date'){
                    $blnCreateDate = true;
                }
				
                if (strtolower($col['COLUMN_NAME']) == 'update_date'){
                    $blnUpdateDate = true;
                }
            }

            // 日付の取得
            $strDate = date('Y-m-d H:i:s');

            if ($blnCreateDate == true){
                $arrParams['create_date'] = $strDate;
            }
			
            if ($blnUpdateDate == true){
                $arrParams['update_date'] = $strDate;
            }
        }

        $this->_objDB->insert($strTable, $arrParams);
        return $this->_objDB->lastInsertId();
    }

    /**----------------------------------------------------------------------
     * データの削除を行う
     *
     * @param   string  $strTable          対象となるテーブル
     * @param   string  $strKeyValue       プライマリキーの値
     * @return  none
     *
     ----------------------------------------------------------------------*/
    public function deleteDb($strTable = '', $strKeyValue = '')
    {
        // ユーザー入力値のエスケープ処理
        //$arrKeyValue = $this->exchangeMq(array($strKeyValue));
		
        // 主キー項目の取得
        $strPrimaryKey = $this->setPrimaryKey($strTable);
        $strWhere = array($strPrimaryKey . " = " . $strKeyValue);
		
        // 削除処理の実行
        $this->_objDB->delete($strTable, $strWhere);
    }

	/**----------------------------------------------------------------------
     *
     * @param   string  $strTable          対象となるテーブル
     * @param   string  $strWhere          SQLの条件文
     * @return  none
     *
     ----------------------------------------------------------------------*/
    public function delete($strTable = '', $strWhere = '')
    {
        $this->_objDB->delete($strTable, $strWhere);
    }

    /**----------------------------------------------------------------------
     * Get all like names
     *
     * @param   array  $arrParams          array parameters
     * @return  array	list names
     *
     ----------------------------------------------------------------------*/
    public function getLikeNameByName($arrParams)
    {
        $strItems = $arrParams['name_field'];
        $strTable = $arrParams['table'];
        $strWhere = '';

        if(isset($arrParams['compare_name'])){
            $strRelate = '';
            foreach($arrParams['compare_name'] as $strName){
                $strWhere .= $strRelate . ' RTRIM(lower(' . $arrParams['name_field'] . ')) like RTRIM(lower(\'' . $strName . '\')) ';
                $strRelate = ' OR ';
            }
        }
        $strOption = ' ORDER BY lower(' . $arrParams['name_field'] . ') ASC ';

        $arrQuery = $this->selectDb($strItems, $strTable, $strWhere, array(''), $strOption);

        return $arrQuery;
    }

    /**----------------------------------------------------------------------
     * Begin transaction
	 * @return  none
     *
     ----------------------------------------------------------------------*/
    public function beginTransaction()
    {
        $this->_objDB->beginTransaction();
    }

    /**----------------------------------------------------------------------
     * Commit transaction
	 * @return  none
     *
     ----------------------------------------------------------------------*/
    public function commit()
    {
        $this->_objDB->commit();
    }

    /**----------------------------------------------------------------------
     * Rollback transaction
	 * @return  none
     *
     ----------------------------------------------------------------------*/
    public function rollBack()
    {
        $this->_objDB->rollBack();
    }
}
